package com.ideaaedi.springcloud.jd.user.controller.sys;

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.ideaaedi.commonspring.annotation.RecordParameters;
import com.ideaaedi.springcloud.jd.commonds.constant.BaseConstant;
import com.ideaaedi.springcloud.jd.commonds.constant.JdSymbolConstant;
import com.ideaaedi.springcloud.jd.commonds.entity.PageInfo;
import com.ideaaedi.springcloud.jd.commonds.entity.Result;
import com.ideaaedi.springcloud.jd.commonds.entity.user.po.SysFilePO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.req.SysFileListReqVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.resp.SysFileBatchUploadRespVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.resp.SysFileDetailRespVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.resp.SysFileDownloadImgRespVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.resp.SysFileListRespVO;
import com.ideaaedi.springcloud.jd.user.service.SysFileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 系统 - 文件上传下载
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 2021.0.1.A
 */
@Slf4j
@RestController
@ApiSort(value = 4)
@RequestMapping("/sys-file")
@Api(value = "系统-文件", tags = {"系统-文件"})
public class SysFileController {
    
    @Resource
    private SysFileService sysFileService;
    
    @Resource
    private HttpServletResponse response;
    
    /**
     * 文件上传
     *
     * @param file
     *         文件
     *
     * @return 文件id
     */
    @PostMapping("/upload")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "文件上传")
    public Result<SysFileDetailRespVO> upload(@ApiParam(value = "单个文件. 参数名为：file", required = true)
                                              @RequestParam(value = "file") MultipartFile file,
                                              @ApiParam(value = "租户")
                                              @RequestParam(value = BaseConstant.TENANT, required = false) String tenant) {
        return Result.success(sysFileService.upload(file, tenant));
    }
    
    /**
     * 文件批量上传
     *
     * @param fileList 文件集合
     *
     * @return 文件id-文件名 map
     */
    @ApiOperationSupport(order = 2)
    @PostMapping("/batch-upload")
    @ApiOperation(value = "文件批量上传")
    public Result<SysFileBatchUploadRespVO> batchUpload(@ApiParam(value = "多个文件. 参数名为：fileList", required = true)
                                                        @RequestParam(value = "fileList")  List<MultipartFile> fileList,
                                                        @ApiParam(value = "租户")
                                                        @RequestParam(value = BaseConstant.TENANT, required = false) String tenant) {
        return Result.success(sysFileService.batchUpload(fileList, tenant));
    }
    
    /**
     * 查列表
     *
     * @param req 参数
     *
     * @return 数据列表
     */
    @PostMapping("/list")
    @ApiOperation(value = "查列表")
    @ApiOperationSupport(order = 3)
    public Result<PageInfo<SysFileListRespVO>> list(@RequestBody @Validated SysFileListReqVO req) {
        return Result.success(sysFileService.list(req));
    }
    
    /**
     * 查详情
     *
     * @param id 要查询数据的id
     *
     * @return 数据详情
     */
    @GetMapping("/detail/{id}")
    @ApiOperation(value = "查详情")
    @ApiOperationSupport(order = 4)
    public Result<SysFileDetailRespVO> detail(@ApiParam(value = "要查询数据的id", required = true)
                                              @PathVariable("id") @NotNull(message = "id cannot be null.") Long id) {
        return Result.success(sysFileService.detail(id));
    }
    
    /**
     * 文件下载
     *
     * @param fileId
     *         文件id
     */
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "文件下载")
    @GetMapping("/download-file/{fileId}")
    public void downloadFile(@ApiParam(value = "文件id", required = true) @NotNull(message = "fileId不能为空")
                             @PathVariable("fileId") Long fileId) throws IOException {
        Pair<SysFilePO, byte[]> fileNameAndContentPair = sysFileService.loadFile(fileId);
        SysFilePO po = fileNameAndContentPair.getLeft();
        String contentType = po.getContentType();
        if (StringUtils.isNotBlank(contentType)) {
            response.setHeader("content-type", contentType);
            response.setContentType(contentType);
        } else {
            response.setContentType("application/octet-stream");
        }
        String originalFilename = po.getOriginalFilename();
        originalFilename = URLEncoder.encode(originalFilename, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");
        response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + originalFilename);
        response.getOutputStream().write(fileNameAndContentPair.getRight());
    }
    
    /**
     * 图片base64下载
     *
     * @param fileId
     *         文件id
     *
     * @return 图片信息
     */
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "图片base64下载")
    @GetMapping("/download-base64-img/{fileId}")
    @RecordParameters(strategy = RecordParameters.Strategy.INPUT)
    public Result<SysFileDownloadImgRespVO> downloadBase64Img(@ApiParam(value = "文件id", required = true) @NotNull(message = "fileId不能为空")
                                                          @PathVariable("fileId") Long fileId) {
        SysFileDownloadImgRespVO resp = sysFileService.downloadImg(fileId);
        log.info("downloadImg return -> {}", resp.briefInfo());
        return Result.success(resp);
    }
    
    /**
     * 图片base64批量下载
     *
     * @param fileIds
     *         文件id（多个使用逗号分割）
     *
     * @return 图片信息
     */
    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "图片base64批量下载")
    @GetMapping("/batch-download-base64-img/{fileIds}")
    @RecordParameters(strategy = RecordParameters.Strategy.INPUT)
    public Result<List<SysFileDownloadImgRespVO>> batchDownloadBase64Img(@ApiParam(value = "文件id（多个使用逗号分割）", required = true)
                                                                     @NotBlank(message = "fileIds不能为空") @PathVariable("fileIds") String fileIds) {
        Set<Long> fileIdSet = Arrays.stream(fileIds.split(JdSymbolConstant.COMMA))
                .filter(StringUtils::isNotBlank)
                .map(idStr -> Long.parseLong(idStr.trim())).collect(Collectors.toSet());
        List<SysFileDownloadImgRespVO> resp = sysFileService.batchDownloadImg(fileIdSet);
        log.info("downloadImg return -> {}", resp.stream().map(SysFileDownloadImgRespVO::briefInfo).collect(Collectors.toList()));
        return Result.success(resp);
    }
}
